<?php
// +----------------------------------------------------------------------
// | ThinkPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2008 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$

/**
 +------------------------------------------------------------------------------
 * ThinkPHP 视图Model类
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id$
 +------------------------------------------------------------------------------
 */
class ViewModel extends Model
{
	protected $viewFields	=	array();
	protected $viewCondition	=	null;
	/**
     +----------------------------------------------------------
     * 强制刷新数据表信息
     +----------------------------------------------------------
     * @access private
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
	public function flush() {
		// 缓存视图模型的字段信息
		$this->fields = array();
		$this->fields['_autoInc'] = false;
		foreach ($this->viewFields as $name=>$val){
            $k = isset($val['_as'])?$val['_as']:$name;
			foreach ($val as $key=>$field){
				if(is_numeric($key)) {
					$this->fields[]	=	$k.'.'.$field;
				}else{
					$this->fields[]	=	$k.'.'.$key;
				}
			}
		}
		$identify	=	$this->name.'_fields';
		// 永久缓存数据表信息
		// 保存在项目的Data目录
		Think::fastCache($identify,$this->fields);
	}

	/**
     +----------------------------------------------------------
     * 得到完整的数据表名
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
	public function getTableName()
	{
		if(empty($this->trueTableName)) {
            $tableName = '';
            foreach ($this->viewFields as $key=>$view){
                $Model  =   D($key);
                if($Model) {
                    // 存在模型 获取模型定义的数据表名称
                    $tableName .= $Model->getTableName();
                }else{
                    // 直接把key作为表名来对待
                    $viewTable  = !empty($this->tablePrefix) ? $this->tablePrefix : '';
                    $viewTable .= $key;
                    $viewTable .= !empty($this->tableSuffix) ? $this->tableSuffix : '';
                    $tableName .= strtolower($viewTable);
                }
                if(isset($view['_as'])) {
                    $tableName .= ' '.$view['_as'];
                }else{
                    $tableName .= ' '.$key;
                }
                if(isset($view['_on'])) {
                    // 支持ON 条件定义
                    $tableName .= ' ON '.$view['_on'];
                }
                if(!empty($view['_type'])) {
                    // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
                    $type = $view['_type'];
                }else{
                    $type = '';
                }
                $tableName   .= ' '.strtoupper($type).' JOIN ';
                $len  =  strlen($type.'_JOIN ');
            }
            $tableName = substr($tableName,0,-$len);
            $this->trueTableName    =   $tableName;
		}
		return $this->trueTableName;
	}

	/**
     +----------------------------------------------------------
     * 检查条件中的视图字段
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $data 条件表达式
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
	public function checkCondition($data) {
		 if(empty($data)) {
			 $data = $this->viewCondition;
		 }else {
			$data	 =	 $this->_facade($data);
			$baseCondition = !empty($this->viewCondition)?$this->viewCondition:array();
			$view	=	array();
			// 检查视图字段
			foreach ($this->viewFields as $key=>$val){
                $k = isset($val['_as'])?$val['_as']:$key;
				foreach ($data as $name=>$value){
					if(false !== $field = array_search($name,$val)) {
						// 存在视图字段
						if(is_numeric($field)) {
							$_key	=	$k.'.'.$name;
						}else{
							$_key	=	$k.'.'.$field;
						}
						$view[$_key]	=	$value;
						unset($data[$name]);
						if(is_array($baseCondition) && isset($baseCondition[$_key])) {
							// 组合条件处理
							$view[$_key.','.$_key]	=	array($value,$baseCondition[$_key]);
							unset($baseCondition[$_key]);
							unset($view[$_key]);
						}
					}
				}
			}
			$data	 =	 array_merge($data,$baseCondition,$view);
		 }
		return $data;
	}

	/**
     +----------------------------------------------------------
     * 检查fields表达式中的视图字段
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $fields 字段
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
	public function checkFields($fields) {
		if(empty($fields) || '*'==$fields ) {
			// 获取全部视图字段
			$fields	=	array();
			foreach ($this->viewFields as $name=>$val){
                $k = isset($val['_as'])?$val['_as']:$name;
				foreach ($val as $key=>$field){
					if(is_numeric($key)) {
						$fields[]	 =	 $k.'.'.$field.' AS '.$field;
					}else{
						$fields[]	 =	 $k.'.'.$key.' AS '.$field;
					}
				}
			}
		}else{
			$fields	=	explode(',',$fields);
			// 解析成视图字段
			foreach ($this->viewFields as $name=>$val){
                $k = isset($val['_as'])?$val['_as']:$name;
				foreach ($fields as $key=>$field){
					if(false !== $_field = array_search($field,$val)) {
						// 存在视图字段
						if(is_numeric($_field)) {
							$fields[$key]	 =	 $k.'.'.$field.' AS '.$field;
						}else{
							$fields[$key]	 =	 $k.'.'.$_field.' AS '.$field;
						}
					}
				}
			}
		}
		$fields = implode(',',$fields);
		return $fields;
	}

	/**
     +----------------------------------------------------------
     * 检查Order表达式中的视图字段
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $order 字段
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
	public function checkOrder($order) {
		 if(!empty($order)) {
			$orders = explode(',',$order);
			$_order = array();
			foreach ($orders as $order){
				$array = explode(' ',$order);
				$field	 =	 $array[0];
				$sort	 =	 isset($array[1])?$array[1]:'ASC';
				// 解析成视图字段
				foreach ($this->viewFields as $name=>$val){
                    $k = isset($val['_as'])?$val['_as']:$name;
					if(false !== $_field = array_search($field,$val)) {
						// 存在视图字段
						if(is_numeric($_field)) {
							$field =	 $k.'.'.$field;
						}else{
							$field	 =	 $k.'.'.$_field;
						}
						break;
					}
				}
				$_order[] = $field.' '.$sort;
			}
			$order = implode(',',$_order);
		 }
		return $order;
	}

	/**
     +----------------------------------------------------------
     * 检查Group表达式中的视图字段
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $group 字段
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
	public function checkGroup($group='') {
		 if(!empty($group)) {
			$groups = explode(',',$group);
			$_group = array();
			foreach ($groups as $group){
				$array = explode(' ',$group);
				$field	 =	 $array[0];
				$sort	 =	 isset($array[1])?$array[1]:'';
				// 解析成视图字段
				foreach ($this->viewFields as $name=>$val){
                    $k = isset($val['_as'])?$val['_as']:$name;
					if(false !== $_field = array_search($field,$val)) {
						// 存在视图字段
						if(is_numeric($_field)) {
							$field =	 $k.'.'.$field;
						}else{
							$field	 =	 $k.'.'.$_field;
						}
						break;
					}
				}
				$_group[$field] = $field.' '.$sort;
			}
		 }
		$group	=	trim($_group);
		return $group;
	}

	public function _before_select($options=array()) {
		return $this->checkView($options);
	}

	protected function checkView($options) {
        if(isset($options['condition'])) {
            $options['condition']	=	$this->checkCondition($options['condition']);
        }
        if(isset($options['field'])) {
            $options['field']			=	$this->checkFields($options['field']);
        }
        if(isset($options['order'])) {
            $options['order']		=	$this->checkOrder($options['order']);
        }
        if(isset($options['group'])) {
            $options['group']		=	$this->checkGroup($options['group']);
        }
		return $options;
	}

    public function add($data='',$options=array()) {
        if(empty($data)) {
            if(!empty($this->options['data'])) {
                $data    =   $this->options['data'];
            }elseif(!empty($this->data)){
                $data    =   $this->data;
            }else{
                $this->error     =   L('_DATA_TYPE_INVALID_');
                return false;
            }
        }
        $data    =   $this->_facade($data);
        // 分析数据到视图模型中的各个表
        foreach ($this->viewFields as $table=>$fields){
            $model  =  D($table);
            foreach ($fields as $field){
                if(false !== $_field = array_search($field,$data)) {
                    if(is_numeric($_field)) {
                        $model->$field    = $data[$field];
                    }else{
                        $model->$_field   =  $data[$field];
                    }
                }
            }
            $model->add();
        }
    }
};
?>